﻿#include <stdio.h>
#include "nalu.h"
#include "stream.h"
#include "slice.h"
#include <vector>
#include <iostream>
#include "output.h"
#include "clipp.h"
#include <fstream>
slice_t *currentSlice; // 当前正在解码的slice
using namespace clipp;


int main(int argc, char * argv[]) {

	//初始默认值
	int fps = 30;
	int start_nalu = 1;
	int end_nalu = INT_MAX;
	//start和end跟analyzer那个软件的提取的nalu序号一样，从1开始
	string h264_url = "1.h264";
	string save_csv_path = " ";
	long long buffer_size = 50 * 1024 * 1024;
	int help = -1;

	auto cli = (
		option("--start", "-s") & value("times", start_nalu),
		option("--end", "-e") & value("times", end_nalu),
		option("--fps", "-f") & value("times", fps),
		option("--save", "-i") & value("times", save_csv_path),
		option("--size", "-m") & value("times", buffer_size),
		option("--open", "-o") & value("times", h264_url),
		option("-") & value("times", help)
		);

	parse(argc, argv, cli);

	if (help != -1) {
		cout << "【show define information and please input again】" << endl;
		cout << "-s, --start		start_nalu (default = 1)" << endl;
		cout << "-e, --end		end_nalu (default = all)" << endl;
		cout << "-f, --fps		fps (default = 30)" << endl;
		cout << "-o, --open	*.h264	h264_url (default = 1.h264)" << endl;
		cout << "-i, --save		save_csv_path (default：don't save)" << endl;
		cout << "-m, --size	*.csv	buffer_size (default = 50*1024*1024)" << endl;
		cout << "-h, --help, -*		(define information)" << endl;
		return -1;
	}

	//经过修改后的值
	cout << "【input_infomation】" << endl;
	// -f fps

	cout << "fps = " << fps << endl;
	// -s start
	if (start_nalu == 1) {
		cout << "start_nalu = 1 (default)" << endl;
	}
	else {
		cout << "start_nalu = " << start_nalu << endl;
	}
	// -e end
	if (end_nalu == INT_MAX) {
		cout << "end_nalu = all_to_end（default）" << endl;
	}
	else {
		cout << "end_nalu = " << end_nalu << endl;
	}
	// -o h264_url
	if (h264_url != "1.h264") {
		cout << "h264_url = " << h264_url << endl;
	}
	else {
		cout << "h264_url = 1.h264(default)" << endl;
	}
	// -i save_csv_path
	if (save_csv_path == " ") {
		cout << "do not save datas in local" << endl;
	}
	else {
		cout << "save_csv_path = " << save_csv_path << endl;
	}
	// -m bufsize
	if (buffer_size != 50 * 1024 * 1024) {
		cout << "buffer_size = " << buffer_size << endl;
	}
	else {
		cout << "buffer_size = 50 * 1024 * 1024(default)" << endl;
	}
	cout << endl << endl;

	// 0. 读取h264文件
	const char* url = h264_url.data();
	int buff_size = readAnnexbBitStreamFile(url, buffer_size);
	if (buff_size == 0) {
		cout << "Check the appropriate value： h264_url  or  buffer_size" << endl;
		return -1;
	}


	// 1. 开辟nalu_t保存nalu_header和SODB
	nalu_t *nalu = allocNalu(buffer_size);
	currentSlice = allocSlice();
	int nalu_i = 0;
	int curr_nal_start = 0;  // 当前找到的nalu起始位置
	int curr_find_index = 0; // 当前查找的位置索引

	
	// 2.在输入的有效区间内，保存h264码流中的各个nalu
	vector<signal_nalu> all_nalu;

	
	//start_nalu默认从第一个开始
	//如果配置的话也要从1到INT_MAX
	int idx = 0;
	while ((nalu->len = find_nal_unit(nalu, buff_size, &curr_nal_start, &curr_find_index)) > 0) {
		//printf("nalu: %d, start: %d, index: %d, size: %d\n", nalu_i, curr_nal_start, curr_find_index, curr_find_index - curr_nal_start);
		idx++;
		nalu_i++;
		if (idx < start_nalu) {
			continue;
		}

		if (idx > end_nalu)
			break;

		signal_nalu sig_nalu;
		sig_nalu.m_num = nalu_i;
		sig_nalu.m_len = curr_find_index - curr_nal_start;

		// 读取/解析 nalu
		read_nal_unit(nalu, sig_nalu);
		all_nalu.emplace_back(sig_nalu);
	}

	//输出到终端
	out *terminal_output = new out;
	terminal_output->out_put(all_nalu, fps, start_nalu, end_nalu);


	if (save_csv_path != " ") {
		const char * save_url = save_csv_path.data();
		ofstream p;
		p.open(save_url, ios::out | ios::trunc);

		//（帧的数据）excel里面是：num、len、nal_ref_idc、slice_type、avg_qp，共5列
		for (auto it : terminal_output->all_frame) {
			p << to_string(it.m_num + 1) << "," << to_string(it.m_total_len) << "," << to_string(it.m_nal_ref_idc) << ","
				<< to_string(it.m_slice_type) << "," << to_string(it.m_avg_qp) << endl; //avg_qp 要加上minus26
		}
		p.close();
	}


	delete terminal_output;
	freeSlice(currentSlice);
	freeNalu(nalu);
	freeFilebuffer();
	return 0;
}
